package fun.codedesign.principle.advice151.a107;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

import fun.codedesign.principle.advice151.Notice;

interface Feature {
    void load();
}

interface Animal {
    void dostuff();
}

/**
 * <br>
 * <pre>
 * </pre>
 *
 * @author zengjian
 * @create 2018-07-08 15:13
 * @since 1.0.0
 */
@Notice("将对象与行为进行解耦")
public class DecorateProxy {
    public static void main(String[] args) {
        Animal jerry = new Jerry();
        jerry.dostuff();
        jerry = new DecorateAnimal(jerry, FlyFeature.class);
        jerry.dostuff();
        jerry = new DecorateAnimal(jerry, Swimming.class);
        jerry.dostuff();
    }
}

class DecorateAnimal implements Animal {

    private Animal animal;
    private Class<? extends Feature> clz;

    public DecorateAnimal() {
    }

    public DecorateAnimal(Animal animal, Class<? extends Feature> clz) {
        this.animal = animal;
        this.clz = clz;
    }

    @Override
    public void dostuff() {
        InvocationHandler handler = new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                Object obj = null;
                if (Modifier.isPublic(method.getModifiers())) {
                    obj = method.invoke(clz.newInstance(), args);
                }
                animal.dostuff();
                return obj;
            }
        };
        // 类加载器
        ClassLoader cl = getClass().getClassLoader();
        Feature proxy = (Feature) Proxy.newProxyInstance(cl, clz.getInterfaces(), handler);
        proxy.load();
    }
}

class FlyFeature implements Feature {

    @Override
    public void load() {
        System.out.println("会飞了");
    }
}

class Swimming implements Feature {

    @Override
    public void load() {
        System.out.println("会游泳了");
    }

}

class Jerry implements Animal {

    @Override
    public void dostuff() {
        System.out.println("我是jerry");
    }
}
